
#ifndef WORK_STEALING_H
#define WORK_STEALING_H

#include <semaphore.h>
#include <stdlib.h>
#include <iostream>
#include <mpi.h>
#include <time.h>
#include "parser.h"

// MPI TAGS
#define TAG_REQUEST		0
#define	TAG_WORKSTEAL_REQUEST	1
#define TAG_WORKSTEAL_ANSWER	2
#define TAG_UPDATE_NODE			3
#define TAG_UPDATE_NODE_NEW_OWNER	4
#define TAG_NODE_END		5
#define TAG_LAST_TASK_END	6

using namespace std;

extern	pthread_mutex_t	nodes_ready_mutex;
extern	pthread_mutex_t	nodes_blocked_mutex;

extern	bool all_tasks_ended;

extern	int root_node_id;

extern	void task_ended_message_received(int task_dep_id,int task_ended_id);

/*
 * Here are described threads and functions which are in charge of work stealing mechanism and MPI nodes communication
 */

// Errors handling
void print_MPI_error(int error_code);

// Thread handling all communications
void * communication_dispatcher_function(void *arg);

// Work stealing
void work_stealing();

//void work_stealing_undergone_thread_function(int machine_source_id);
void *work_stealing_undergone_thread_function(void *arg);

// Node update
void update_node(Node *node_to_prevent, int node_id, int new_machine_owner_id);

void update_node_thread_function(int machine_source_id);

// Prevent tasks end, for dependencies
void task_end(Node *node_to_prevent, int node_ended_id);

void *task_end_thread_function(void *arg);

// Be aware when last node is being executed
void *last_node_thread_function(void *arg);

#endif

